package com.tmsps.ne4weixin.utils;

import java.util.Map;

import com.tmsps.ne4weixin.bean.message.event.BaseEvent;
import com.tmsps.ne4weixin.bean.message.event.LocationEvent;
import com.tmsps.ne4weixin.bean.message.event.MenuEvent;
import com.tmsps.ne4weixin.bean.message.event.QrsceneEvent;
import com.tmsps.ne4weixin.bean.message.event.SubscribeEvent;
import com.tmsps.ne4weixin.bean.message.receive.ImageMessageVo;
import com.tmsps.ne4weixin.bean.message.receive.InBaseMessage;
import com.tmsps.ne4weixin.bean.message.receive.LinkMessageVo;
import com.tmsps.ne4weixin.bean.message.receive.LocationMessageVo;
import com.tmsps.ne4weixin.bean.message.receive.ShortVideoMessageVo;
import com.tmsps.ne4weixin.bean.message.receive.TextMessageVo;
import com.tmsps.ne4weixin.bean.message.receive.VideoMessageVo;
import com.tmsps.ne4weixin.bean.message.receive.VoiceMessageVo;
import com.tmsps.ne4weixin.config.enumeration.EventTypeEnum;
import com.tmsps.ne4weixin.config.enumeration.MsgTypeEnum;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Console;
import lombok.extern.slf4j.Slf4j;

/**
 * @Title:  WeiXinMsgUtil.java
 * @Package com.tmsps.ne4weixin.utils
 * @Description: 微信消息处理工具
 * @author: zhangwei
 * @date:   2020-03-10
 */
@Slf4j
public class WeiXinMsgUtil {
	/**
	 * @Title: xmlToMap
	 * @Description: 将解码后的微信消息转化为MAP
	 * @author:zhangwei
	 * @date: Mar 10, 2020 1:55:31 PM
	 * @param: @param message
	 * @param: @return      
	 * @return: Map<String,String>      
	 * @throws
	 */
	public static Map<String, String> xmlToMap(String message) {
		return XmlUtils.getXmlToMap(message);
	}
	
	/**
	 * @Title: getMsgType
	 * @Description: 这里需要传入的是解密后的XML格式的字符串
	 * @author:zhangwei
	 * @date: Mar 10, 2020 10:33:19 AM
	 * @param: @param message
	 * @param: @return      
	 * @return: String      
	 * @throws
	 */
	public static String getMsgType(String message) {
		Map<String, String> xmlMap = xmlToMap(message);
		return xmlMap.get(MsgTypeEnum.MsgType.toName());
	}
	
	public static String getMsgType(Map<String,String> messageMap) {
		return messageMap.get(MsgTypeEnum.MsgType.toName());
	}
	
	/**
	 * @Title: toMessageBean
	 * @Description: 将接收到的消息封装为消息BEAN实体
	 * @author:zhangwei
	 * @date: Mar 10, 2020 10:44:13 AM
	 * @param: @param message
	 * @param: @return      
	 * @return: BaseMessage      
	 * @throws
	 */
	public static InBaseMessage toMessageBean(String message) {
		/**
		 * 判断消息类型，根据目前微信的文档说明，消息类型主要有七种类型：
		 * 文本为text
		 * 图片为image
		 * 语音为voice 请注意，开通语音识别后，用户每次发送语音给公众号时，微信会在推送的语音消息XML数据包中，增加一个Recognition字段（注：由于客户端缓存，开发者开启或者关闭语音识别功能，对新关注者立刻生效，对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试）。
		 * 视频为video
		 * 小视频为shortvideo
		 * 地理位置为location
		 * 链接为link
		 * https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
		 */
		Map<String, String> xmlMap = xmlToMap(message);
		return toMessageBean(xmlMap);
	}
	
	public static InBaseMessage toMessageBean(Map<String,String> messageXML) {
		String msgType = getMsgType(messageXML);

		if (MsgTypeEnum.IMAGE.toName().equals(msgType)) {
			ImageMessageVo ImageMessageVo = BeanUtil.fillBeanWithMap(messageXML, new ImageMessageVo(), false);
			log.debug("将接收到的消息封装为【图片】VO：{}",ImageMessageVo.toString());
			return ImageMessageVo;
		}
		if (MsgTypeEnum.LINK.toName().equals(msgType)) {
			LinkMessageVo LinkMessage = BeanUtil.fillBeanWithMap(messageXML, new LinkMessageVo(), false);
			log.debug("将接收到的消息封装为【链接】VO：{}",LinkMessage.toString());
			return LinkMessage;
		}

		if (MsgTypeEnum.LOCATION.toName().equals(msgType)) {
			LocationMessageVo LocationMessage = BeanUtil.fillBeanWithMap(messageXML, new LocationMessageVo(), false);
			log.debug("将接收到的消息封装为【坐标】VO：{}",LocationMessage.toString());
			return LocationMessage;
		}
		
		if (MsgTypeEnum.SHORT_VIDEO.toName().equals(msgType)) {
			ShortVideoMessageVo ShortVideoMessage = BeanUtil.fillBeanWithMap(messageXML, new ShortVideoMessageVo(), false);
			log.debug("将接收到的消息封装为【短视频】VO：{}",ShortVideoMessage.toString());
			return ShortVideoMessage;
		}
		
		if (MsgTypeEnum.TEXT.toName().equals(msgType)) {
			TextMessageVo TextMessage = BeanUtil.fillBeanWithMap(messageXML, new TextMessageVo(), false);
			log.debug("将接收到的消息封装为【文本】VO：{}",TextMessage.toString());
			return TextMessage;
		}
		
		if (MsgTypeEnum.VIDEO.toName().equals(msgType)) {
			VideoMessageVo VideoMessage = BeanUtil.fillBeanWithMap(messageXML, new VideoMessageVo(), false);
			log.debug("将接收到的消息封装为【视频】VO：{}",VideoMessage.toString());
			return VideoMessage;
		}
		
		if (MsgTypeEnum.VOICE.toName().equals(msgType)) {
			VoiceMessageVo VoiceMessage = BeanUtil.fillBeanWithMap(messageXML, new VoiceMessageVo(), false);
			log.debug("将接收到的消息封装为【语音】VO：{}",VoiceMessage.toString());
			return VoiceMessage;
		}
		log.warn("未能将接收到的消息做转换:{}",messageXML);	
		return null;
	}
	
	/**
	 * @Title: toEventBean
	 * @Description: 将微信消息封装为微信事件BEAN
	 * @author:zhangwei
	 * @date: Mar 10, 2020 3:51:39 PM
	 * @param: @param messageXML
	 * @param: @return      
	 * @return: BaseEvent      
	 * @throws
	 */
	public static BaseEvent toEventBean(Map<String, String> messageXML) {
		// 获取event事件标识
		String Event = messageXML.get(EventTypeEnum.Event.toName());
		CopyOptions copyOptions = CopyOptions.create().ignoreCase().ignoreError();
		
		if(EventTypeEnum.SUBSCRIBE.toName().equals(Event)) {
			SubscribeEvent subscribeEvent = BeanUtil.fillBeanWithMap(messageXML, new SubscribeEvent(), copyOptions);
			log.debug("将接收到的事件消息封装为【关注事件】：{}",subscribeEvent.toString());
			return subscribeEvent;
		}
		
		if(EventTypeEnum.UNSUBSCRIBE.toName().equals(Event)) {
			SubscribeEvent subscribeEvent = BeanUtil.fillBeanWithMap(messageXML, new SubscribeEvent(), copyOptions);
			log.debug("将接收到的事件消息封装为【取消关注事件】：{}",subscribeEvent.toString());
			return subscribeEvent;
		}
		
		if(EventTypeEnum.SCAN.toName().equals(Event)) {
			QrsceneEvent qrsceneEvent = BeanUtil.fillBeanWithMap(messageXML, new QrsceneEvent(), copyOptions);
			log.debug("将接收到的事件消息封装为【扫码事件】：{}",qrsceneEvent.toString());
			return qrsceneEvent;
		}
		
		if(EventTypeEnum.LOCATION.toName().equals(Event)) {
			LocationEvent locationEvent = BeanUtil.fillBeanWithMap(messageXML, new LocationEvent(), copyOptions);
			log.debug("将接收到的事件消息封装为【上报地理位置事件】：{}",locationEvent.toString());
			return locationEvent;
		}
		
		if(EventTypeEnum.CLICK.toName().equals(Event)) {
			MenuEvent menuEvent = BeanUtil.fillBeanWithMap(messageXML, new MenuEvent(), copyOptions);
			Console.log("将接收到的事件消息封装为【菜单点击事件】：{}",menuEvent);
			log.debug("将接收到的事件消息封装为【菜单点击事件】：{}",menuEvent.toString());
			return menuEvent;
		}
		
		if(EventTypeEnum.VIEW.toName().equals(Event)) {
			MenuEvent menuEvent = BeanUtil.fillBeanWithMap(messageXML, new MenuEvent(), copyOptions);
			log.debug("将接收到的事件消息封装为【菜单跳转链接事件】：{}",menuEvent.toString());
			return menuEvent;
		}

		log.warn("未能将接收到的消息做转换:{}", messageXML);
		return null;
	}
	
}
